package com.slanmao.common.utils;

import com.google.gson.Gson;
import com.slanmao.common.entity.QRcode;
import com.slanmao.exception.CommonException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Map;

/**
 * Http工具类
 */
@Slf4j
@Component
public class HttpUtils {

    private String qr_url="https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s";


    @Autowired
    TokenUtils tokenUtils;



    /**
     * 发送POST请求
     *
     * @param url  请求url
     * @param data 请求数据
     * @return 结果
     */
    @SuppressWarnings("deprecation")
    public String post(String url, String data) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(10000).setConnectTimeout(20000)
                .setConnectionRequestTimeout(10000).build();
        httpPost.setConfig(requestConfig);
        String context = StringUtils.EMPTY;
        if (!StringUtils.isEmpty(data)) {
            StringEntity body = new StringEntity(data, "utf-8");
            httpPost.setEntity(body);
        }
        // 设置回调接口接收的消息头
        httpPost.addHeader("Content-Type", "application/json");
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            context = EntityUtils.toString(entity, HTTP.UTF_8);
            return context;
        } catch (Exception e) {
            e.getStackTrace();
        } finally {
            try {
                response.close();
                httpPost.abort();
                httpClient.close();
            } catch (Exception e) {
                e.getStackTrace();
            }
        }
        return context;
    }



    /**
     * 发送 get请求
     */
    public String get(String url) {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            // 创建httpget.
            HttpGet httpget = new HttpGet(url);
            log.info("executing request " + httpget.getURI());
            // 执行get请求.
            CloseableHttpResponse response = httpclient.execute(httpget);
            try {
                // 获取响应实体
                HttpEntity entity = response.getEntity();
                // 打印响应状态
                if (entity != null) {
                    // 打印响应内容长度
                    String responseJson = EntityUtils.toString(entity);
                    log.info("Response content: " + response);
                    return responseJson;
                }
                return null;
            } finally {
                response.close();
            }
        } catch (IOException | ParseException e) {
            e.printStackTrace();
        } finally {
            // 关闭连接,释放资源
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 获取微信临时二维码图片链接
     * @param scenStr 场景值 动态数据
     * @param token accessToken
     * @return url
     * @throws CommonException
     */
    public String getQRImage(String scenStr,String token) throws CommonException {
        String qrurl = String.format(qr_url, token);

        Map<String,Object> postData = new HashMap<>();
        //30天过期
        postData.put("expire_seconds",2592000);
        //字符串形式场景值
        postData.put("action_name","QR_STR_SCENE");

        Map<String,String> scene_str = new HashMap<>();
        scene_str.put("scene_str",scenStr);

        Map<String,Map> scene = new HashMap<>();

        scene.put("scene",scene_str);

        postData.put("action_info",scene);

        //最终数据结构为{"expire_seconds": 2592000, "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": "xxxx"}}}

        //使用HTTPPost方法访问获取二维码链接url

        HttpPost httpPost = new HttpPost(qrurl);

        //创建http连接客户端

        CloseableHttpClient client = HttpClients.createDefault();

        //设置头响应类型
        httpPost.addHeader("Content-Type", "application/json");
        try {
            // 设置请求的参数
            String jsonRequest = new Gson().toJson(postData);
            httpPost.setEntity(new StringEntity(jsonRequest, "UTF-8"));

            log.info("微信获取微信二维码post数据 " + jsonRequest);
            //返回的post请求结果

            HttpResponse response = client.execute(httpPost);
            HttpEntity httpEntity = response.getEntity();
            if (httpEntity!=null){
                //判断token是否失效
                String jsonResponse = EntityUtils.toString(httpEntity);
                QRcode qRcode = new Gson().fromJson(jsonResponse, QRcode.class);
                //如果微信报错
                if (qRcode.getErrcode()!=null){
                    //报微信token过期
                    if (qRcode.getErrcode()==40001||qRcode.getErrcode()==42001||qRcode.getErrmsg().contains("expired")){
                        //重新刷新access_token
                        String refreshToken = tokenUtils.refreshToken();
                        //重新请求接口
                        return getQRImage(scenStr,refreshToken);
                    }else {
                        //记录一下
                        log.info("生成图片失败!,错误码"+qRcode.getErrcode()+",信息:"+qRcode.getErrmsg());
                        //抛出异常
                        throw new CommonException(100001,"生成图片失败");
                    }

                }else {
                    //没有errcode就返回图片链接
                    return qRcode.getUrl();
                }
            }
        } catch (ConnectionPoolTimeoutException e) {
            log.error("http post throw ConnectionPoolTimeoutException(wait time out)", e);
        } catch (ConnectTimeoutException e) {
            log.error("http post throw ConnectTimeoutException", e);
        } catch (SocketTimeoutException e) {
            log.error("http post throw SocketTimeoutException", e);
        } catch (IOException e) {
            log.error("http post throw IOException", e);
        } finally {
            httpPost.releaseConnection();
        }
        throw new CommonException(100001,"生成图片失败");
}

}
